package test.demo;

import tech.waterism.modelbase.PredictBase;
import tech.waterism.modelbase.PredictResult;
import com.alibaba.fastjson.JSON;

import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 河北雨洪模型 产汇流
 *
 * @author 初京刚
 * @version 1.0
 * @date 2022-4-13
 */

public class HBMODEL extends PredictBase {

    /**
     * 流域面积 km2
     */
    private double Area;

    /**
     * 下渗曲线参数
     */
    private double u;

    /**
     * 稳定下渗率，mm/h
     */
    private double fc;

    /**
     * 流域内最大点下渗能力，mm/h
     */
    private double fm;

    /**
     * 下渗分配曲线参数
     */
    private double n;

    /**
     * 流域平均张力水容量（mm）、流域蓄水容量
     */
    private double Wm;

    /**
     * 流域平均张力水容量（mm）阈值。
     * Pa高于阈值时，供水充分，土壤蒸发等于蒸发能力；Pa低于阈值时，供水不充分，Pa与Z土/Zm约为正比关系。
     */
    private double Wm2;

    /**
     * 流域最大土壤表层湿度（mm）
     */
    private double Im;

    /**
     * 蓄水容量抛物线线指数
     */
    private double b0;

    /**
     * 表层土壤湿度的Pa系数
     */
    private double X;

    /**
     * 1km2的地表水汇流时间（分钟）
     */
    private double As;

    /**
     * 1km2的地下水汇流时间（分钟）
     */
    private double Ag;

    /**
     * 地表水断面形状参数
     */
    private double Bs;

    /**
     * 地下水断面形状参数
     */
    private double Bg;

    /**
     * 地表水上下断面或流域平均最大雨强发生时间至洪峰出现的传播时间（时段）
     */
    private int Ts;

    /**
     * 地下水上下断面或流域平均最大雨强发生时间至洪峰出现的传播时间（时段）
     */
    private int Tg;

    /**
     * 下渗量计算的允许误差
     */
    private double err_limit_f;

    /**
     * 汇流计算的允许误差
     */
    private double err_limit_q;

    /**
     * 流域 月水面蒸发量（mm）
     */
    private double[] ES;

    /**
     * 流域 时段水面蒸发量（mm）
     */
    private double[] floodE;

    /**
     * 降水时间
     */
    private Date[] floodTm;

    /**
     * 降水量
     */
    private double[] floodDrp;

    /**
     * 降水序列长度
     */
    private Integer floodRainRange;

    /**
     * 降水时段长
     */
    private double timeInterval;

    /**
     * 时段初土壤湿度（mm）
     */
    private double[] Pa;

    /**
     * 时段初土壤表层湿度（mm）
     */
    private double[] I;

    /**
     * 净雨
     */
    private double[] PE;

    /**
     * 时段地表径流
     */
    private double[] RS;

    /**
     * 时段地下径流
     */
    private double[] RG;

    /**
     * 时段流域产流
     */
    private double[] R;

    /**
     * 时段末地表出流
     */
    private double[] QS;

    /**
     * 时段末地下出流
     */
    private double[] QG;

    /**
     * 时段末出流
     */
    private double[] QW;

    /**
     * 地表出流状态
     */
    private double[] QS0;

    /**
     * 地下出流状态
     */
    private double[] QG0;

    /**
     * 时段出流状态
     */
    private double[] QW0;

    public HBMODEL(Map<String, String> data) {
        super();
        Area = Double.parseDouble(data.get("F"));
        u = Double.parseDouble(data.get("U"));
        fc = Double.parseDouble(data.get("FC"));
        fm = Double.parseDouble(data.get("FM"));
        n = Double.parseDouble(data.get("N"));
        Wm = Double.parseDouble(data.get("WM"));
        Wm2 = Double.parseDouble(data.get("WMX")) * Wm;
        b0 = Double.parseDouble(data.get("EX"));
        X = Double.parseDouble(data.get("X"));
        Im = X * Wm;
        As = Double.parseDouble(data.get("AS"));
        Ag = Double.parseDouble(data.get("AG"));
        Bs = Double.parseDouble(data.get("BS"));
        Bg = Double.parseDouble(data.get("BG"));
        Ts = Integer.parseInt(data.get("TS"));
        Tg = Integer.parseInt(data.get("TG"));
        ES = JSON.parseObject(data.get("ES"), double[].class);
        floodTm = JSON.parseObject(data.get("dt"), Date[].class);// input[i].data.dt
        floodDrp = JSON.parseObject(data.get("rain"), double[].class);// input[i].data.rain
        floodE = JSON.parseObject(data.get("evaporation"), double[].class);  // input[i].data.evaporation
        floodRainRange = floodDrp.length;
        timeInterval = Double.parseDouble(data.get("clen"));                  // index.clen

        PE = new double[floodRainRange];
        RS = new double[floodRainRange];
        RG = new double[floodRainRange];
        R = new double[floodRainRange];
        QS = new double[floodRainRange];
        QG = new double[floodRainRange];
        QW = new double[floodRainRange];
        QS0 = new double[floodRainRange + 1];
        QG0 = new double[floodRainRange + 1];
        QW0 = new double[floodRainRange + 1];
        QW0[0] = Double.parseDouble(data.get("STARTQ"));
        QS0[0] = QW0[0];
        QG0[0] = QW0[0] - QS0[0];
        Pa = new double[floodRainRange + 1];
        Pa[0] = Double.parseDouble(data.get("PA0"));
        I = new double[floodRainRange + 1];
        I[0] = Double.parseDouble(data.get("I0"));

        err_limit_f = 0.1;
        err_limit_q = 0.01;
    }

    /**
     * 模型计算
     */
    public Map<String, double[]> HBmodel() {

        //产流计算
        CLJS();

        //汇流计算
//        LYHL();
        LYHLP();

        Map<String, double[]> simulationResult = new HashMap<>();
        simulationResult.put("rain", floodDrp);
        simulationResult.put("PE", PE);
        simulationResult.put("RS", RS);
        simulationResult.put("RG", RG);
        simulationResult.put("R", R);
        simulationResult.put("QS", QS);
        simulationResult.put("QG", QG);
        simulationResult.put("QSim", QW);
        return simulationResult;
    }

    /**
     * 产流模型
     *
     * @return 地表产流、地下产流、净雨
     */
    private void CLJS() {
        double EPt; // 时段水面蒸散发（实测蒸发，即ES[]或时段）
        double Fd;  // 时段下渗量

        for (int i = 0; i < floodRainRange; i++) {
            //蒸发计算
            if (floodE == null || floodE.length != floodRainRange) {
                EPt = calcEvaporationPotential(floodTm[i], timeInterval);
            } else {
                EPt = floodE[i];
            }

            // PE[i]为降雨减去蒸发，可正可负
            PE[i] = floodDrp[i] - EPt;

            //如果有净雨产生，地表超渗产流、土壤蓄满产流 *********/
            if (PE[i] > 0) {
                //时段下渗量计算
                Fd = XSJS(i);
                if (Fd < PE[i]) { //地表超渗产流
                    RS[i] = PE[i] - Fd;
                    I[i + 1] = I[i] + Fd;
                } else {
                    RS[i] = 0;
                    Fd = PE[i];
                    //时段末（下一时段初）土壤表层湿度计算
                    IAJS(i, EPt);
                }
                //地下径流计算 土壤蓄满产流
                RGJS(i, Fd);
            } else {
                RS[i] = 0;
                RG[i] = 0;
                //时段末（下一时段初）土壤湿度计算
                PAJS(i, EPt);
                //时段末（下一时段初）土壤表层湿度计算
                IAJS(i, EPt);
            }
            if (I[i + 1] > Pa[i + 1]) {
                I[i + 1] = Pa[i + 1];
            }
            R[i] = RS[i] + RG[i];
        }
    }

    /**
     * 土壤湿度计算
     *
     * @param i 时段
     * @param Z 水面蒸发
     * @return 时段末（下时段初）土壤表层湿度
     */
    private void PAJS(int i, double Z) {
        if (floodDrp[i] > 0) {
            if (floodDrp[i] < Z) {
                if (Pa[i] > Wm2) {
                    Pa[i + 1] = Pa[i] + floodDrp[i] - Z;
                } else {
                    //降雨低于蒸发能力，土壤含水量低于Wm2，降雨会阻碍土壤蒸发、降低土壤蒸发能力？
                    Pa[i + 1] = (1 - (Z - floodDrp[i]) / Wm2) * Pa[i];
                }
            } else {
                if (floodDrp[i] < 20) {
                    if (Pa[i] > Wm2) {
                        Pa[i + 1] = Pa[i] + floodDrp[i] - Z;
                    } else {
                        //降雨超过蒸发能力，土壤含水量低于Wm2，降雨减去产流部分后进入土壤承担土壤蒸发、土壤蒸发能力恢复？
                        Pa[i + 1] = (Pa[i] + floodDrp[i]) * (1 - Z / Wm2);
                    }
                } else {
                    double R = floodDrp[i] * 0.3;
                    if (Pa[i] > Wm2) {
                        Pa[i + 1] = Pa[i] + floodDrp[i] - Z - R;
                    } else {
                        //降雨超过蒸发能力，土壤含水量低于Wm2，降雨减去产流部分后进入土壤承担土壤蒸发、土壤蒸发能力恢复？
                        Pa[i + 1] = (Pa[i] + floodDrp[i] - R) * (1 - Z / Wm2);
                    }
                }
            }
        } else {
            if (Pa[i] > Wm2) {
                Pa[i + 1] = Pa[i] - Z;
            } else {
                Pa[i + 1] = (1 - Z / Wm2) * Pa[i];
            }
        }
        if (Pa[i + 1] > Wm) {
            Pa[i + 1] = Wm;
        }
    }

    /**
     * 地下径流计算 土壤蓄满产流
     *
     * @param i  时段
     * @param Fd 时段下渗量
     * @return 时段地下径流 土壤湿度
     */
    private void RGJS(int i, double Fd) {
        double WW = Wm * (1.0 + b0); // 流域单点最大蓄水容量
        double PP = WW * (1.0 - Math.pow((1.0 - Pa[i] / Wm), 1.0 / (1.0 + b0)));
        if (Fd + PP < WW) {
            RG[i] = Fd + Pa[i] - Wm + Wm * Math.pow((1 - (Fd + PP) / WW), 1 + b0);
        } else {
            RG[i] = Fd + Pa[i] - Wm;
        }
        Pa[i + 1] = Pa[i] + Fd - RG[i];
        if (Pa[i + 1] > Wm) {
            Pa[i + 1] = Wm;
        }
    }

    /**
     * 土壤表层湿度计算
     *
     * @param i 时段
     * @param Z 水面蒸发
     * @return 时段末（下时段初）土壤表层湿度
     */
    private void IAJS(int i, double Z) {
        if (floodDrp[i] > 0) {
            if (floodDrp[i] <= Z) {
                if (I[i] > Wm2) {
                    I[i + 1] = floodDrp[i] + I[i] - Z;
                } else {
                    I[i + 1] = (floodDrp[i] + I[i]) * (1 - Z / Im);
                }
            } else {
                I[i + 1] = floodDrp[i] + I[i] - Z;
            }
        } else {
            if (I[i] > Wm2) {
                I[i + 1] = I[i] - Z;
            } else {
                I[i + 1] = I[i] * (1 - Z / Im);
            }
        }
    }

    /**
     * 时段下渗计算
     *
     * @param i 时段
     * @return 时段下渗量
     */
    private double XSJS(int i) {
        double Px = PE[i] / timeInterval;
        double M;
        double Fd = 0.0;  //时段累积下渗量
        double Fp = 0.0;  //小时积分下渗量
        double Ft = 0.0;  //小时差分下渗量
        double Fi = I[i]; //小时土壤表层湿度

        if (Px < fm) {
            M = Px - Math.pow(Px, n + 1) / (Math.pow(fm, n) * (n + 1));
        } else {
            M = fm - fm / (n + 1);
        }

        for (int t = 0; t < (int) Math.round(timeInterval); t++) {
            Ft = M * Math.exp((-1) * u * Fi) + fc;
            Fp = M * Math.exp((-1) * u * Fi) * (1 - Math.exp((-1) * u * Ft)) / (u * Ft) + fc;
            while (Math.abs(Fp - Ft) / Fp * 100 > err_limit_f) {
                Ft = Fp;
                Fp = M * Math.exp((-1) * u * Fi) * (1 - Math.exp((-1) * u * Ft)) / (u * Ft) + fc;
            }
            Fi = Fi + Fp;
            Fd = Fd + Fp;
        }
        return Fd;
    }

    /**
     * 蒸发计算
     *
     * @param date   降水时间
     * @param timeIn 时间间隔 (h)
     * @return 蒸发
     */
    private double calcEvaporationPotential(Date date, double timeIn) {
        Calendar time = Calendar.getInstance();
        time.setTime(date);
        Integer Month = time.get(Calendar.MONTH) + 1; // 获得降雨开始月份
        double Ep = ES[Month - 1] / 30; // 月蒸发量转换成日蒸发量
        Ep = Ep * timeIn / 24; // 日蒸发量转换成时段蒸发量
        return Ep;
    }

    /**
     * 流域汇流
     * 地面径流、地下径流
     *
     * @return 地表径流汇流、地下径流汇流、总汇流
     */

    private void LYHLP() {
        double A = As * Math.pow(Area, 1.2) / timeInterval / 60;
        double s1, s2, s3, s4;
        double q1, q2, q3, q4;
        double i1, i2, i3;
        double Qstart, Qend;
        for(int i = 0; i < floodRainRange - 1; i++) {
            i1 = (R[i] * Area * 1000) / (3600 * timeInterval);
            i2 = ((R[i] + R[i + 1]) / 2 * Area * 1000) / (3600 * timeInterval);
            i3 = (R[i + 1] * Area * 1000) / (3600 * timeInterval);
            Qstart = QW0[i];
            q1 = Qstart;
            if(q1 <= 0) {
                q1 = 0.0001;
            }
            s1 = (i1 - q1) / A * Math.pow(q1, Bs) * 3600 * timeInterval;
            q2 = q1 + s1 / 2;
            if(q2 <= 0) {
                q2 = 0.0001;
            }
            s2 = (i2 - q2) / A * Math.pow(q2, Bs) * 3600 * timeInterval;
            q3 = q1 + s2 / 2;
            if(q3 <= 0) {
                q3 = 0.0001;
            }
            s3 = (i2 - q3) / A * Math.pow(q3, Bs) * 3600 * timeInterval;
            q4 = q1 + s3;
            if(q4 <= 0) {
                q4 = 0.0001;
            }
            s4 = (i3 - q4) / A * Math.pow(q4, Bs) * 3600 * timeInterval;
            Qend = Qstart + (s1 + 2 * s2 + 2 * s3 + s4) / 6;
            if(Qend < 0) {
                QW[i] = 0.0001;
            } else {
                QW[i] = Qend;
            }

            QW0[i + 1] = QW[i];
        }
    }

    /**
     * 流域汇流
     * 地面径流、地下径流
     *
     * @return 地表径流汇流、地下径流汇流、总汇流
     */

    private void LYHL() {
        double Alpha = 1.2;
        double AAS = As * Math.pow(Area, Alpha) / timeInterval / 60 ;
        double AAG = Ag * Math.pow(Area, Alpha) / timeInterval / 60 ;
        double IAS;//时段地表入流 m3/s
        double IAG;//时段地下入流 m3/s
        double QoS0;//时段初地表出流 m3/s
        double QoG0;//时段初地下出流 m3/s
        double SoS0;//时段初地表蓄水量 m3
        double SoG0;//时段初地下蓄水量 m3
        double QMA;//时段末流量迭代求解已知部分
        double QTT;//时段末流量迭代求解中间判断
        double QTT2;//时段末流量迭代求解主体

        double Ut = 3600 * timeInterval; //时间单位转换

        for (int i = 0; i < floodRainRange; i++) {

            //地表汇流滞时
            if (i < Ts) {
                IAS = 0.0;
            } else {
                IAS = (RS[i - Ts] * Area * 1000) / (3600 * timeInterval);
            }

            //地下汇流滞时
            if (i < Tg) {
                IAG = 0.0;
            } else {
                IAG = (RG[i - Tg] * Area * 1000) / (3600 * timeInterval);
            }

            if (i == 0) {
                QoS0 = QS0[0];
                QoG0 = QG0[0];
            } else {
                QoS0 = QS[i - 1];
                QoG0 = QG[i - 1];
            }

            //地表汇流
            if (IAS > 0.0) {
                if (Bs == 0.5) {
                    QS[i] = Math.pow(((-2) * AAS + Math.pow(
                            4 * AAS * AAS - QoS0 * Ut * Ut + 4 * AAS * Math.pow(QoS0, 1 / 2) * Ut + 2 * IAS * Ut * Ut,
                            1 / 2)) / Ut, 2);
                } else if (Bs == 1.0) {
                    if (QoS0 > 0.0) {
                        SoS0 = AAS * (Math.exp(QoS0) - Math.exp(0.01));
                    } else {
                        SoS0 = 0.0;
                    }
                    QMA = IAS - 0.5 * QoS0 + SoS0 + AAS * Math.exp(0.01);
                    QTT = QoS0;
                    QTT2 = Math.exp((QMA - 0.5 * QTT) * Ut / AAS);
                    while (Math.abs(QTT2 - QTT) > err_limit_q) {
                        QTT = QTT2;
                        QTT2 = Math.exp((QMA - 0.5 * QTT) * Ut / AAS);
                    }
                    QS[i] = QTT2;
                } else if (Bs < 1.0) {
                    QMA = IAS - 0.5 * QoS0 + (AAS / ((1 - Bs) * Ut)) * Math.pow(QoS0, 1 - Bs);
                    QTT = QoS0;
                    QTT2 = Math.pow((QMA - 0.5 * QTT) / (AAS / ((1 - Bs) * Ut)), 1 / (1 - Bs));
                    while (Math.abs(QTT2 - QTT) > err_limit_q) {
                        QTT = QTT2;
                        QTT2 = Math.pow((QMA - 0.5 * QTT) / (AAS / ((1 - Bs) * Ut)), 1 / (1 - Bs));
                    }
                    QS[i] = QTT2;
                } else if (Bs > 1.0) {
                    if (QoS0 > 0.0) {
                        SoS0 = AAS / (1 - Bs) * (Math.pow(QoS0, 1 - Bs) - Math.pow(0.01, 1 - Bs));
                    } else {
                        SoS0 = 0.0;
                    }
                    QMA = IAS - 0.5 * QoS0 + SoS0 + (AAS / ((1 - Bs) * Ut)) * Math.pow(0.01, 1 - Bs);
                    QTT = QoS0;
                    QTT2 = Math.pow((QMA - 0.5 * QTT) / (AAS / ((1 - Bs) * Ut)), 1 / (1 - Bs));
                    while (Math.abs(QTT2 - QTT) > err_limit_q) {
                        QTT = QTT2;
                        QTT2 = Math.pow((QMA - 0.5 * QTT) / (AAS / ((1 - Bs) * Ut)), 1 / (1 - Bs));
                    }
                    QS[i] = QTT2;
                }
            } else { // 退水
                QS[i] = QoS0 * Math.pow(1 + Bs / AAS * Math.pow(QoS0, Bs), (-1) / Bs);
            }
            QS0[i + 1] = QS[i];

            //地下汇流
            if (IAG > 0.0) {
                if (Bg == 0.5) {
                    QG[i] = Math.pow(((-2) * AAG + Math.pow(
                            4 * AAG * AAG - QoG0 * Ut * Ut + 4 * AAG * Math.pow(QoG0, 1 / 2) * Ut + 2 * IAG * Ut * Ut,
                            1 / 2)) / Ut, 2);
                } else if (Bg == 1.0) {
                    if (QoG0 > 0.0) {
                        SoG0 = AAG * (Math.exp(QoG0) - Math.exp(0.01));
                    } else {
                        SoG0 = 0.0;
                    }
                    QMA = IAG - 0.5 * QoG0 + SoG0 + AAG * Math.exp(0.01);
                    QTT = QoG0;
                    QTT2 = Math.exp((QMA - 0.5 * QTT) * Ut / AAG);
                    while (Math.abs(QTT2 - QTT) > err_limit_q) {
                        QTT = QTT2;
                        QTT2 = Math.exp((QMA - 0.5 * QTT) * Ut / AAG);
                    }
                    QG[i] = QTT2;
                } else if (Bg < 1.0) {
                    QMA = IAG - 0.5 * QoG0 + (AAG / ((1 - Bg) * Ut)) * Math.pow(QoG0, 1 - Bg);
                    QTT = QoG0;
                    QTT2 = Math.pow((QMA - 0.5 * QTT) / (AAG / ((1 - Bg) * Ut)), 1 / (1 - Bg));
                    while (Math.abs(QTT2 - QTT) > err_limit_q) {
                        QTT = QTT2;
                        QTT2 = Math.pow((QMA - 0.5 * QTT) / (AAG / ((1 - Bg) * Ut)), 1 / (1 - Bg));
                    }
                    QG[i] = QTT2;
                } else if (Bg > 1.0) {
                    if (QoG0 > 0.0) {
                        SoG0 = AAG / (1 - Bg) * (Math.pow(QoG0, 1 - Bg) - Math.pow(0.01, 1 - Bg));
                    } else {
                        SoG0 = 0.0;
                    }
                    QMA = IAG - 0.5 * QoG0 + SoG0 + (AAG / ((1 - Bg) * Ut)) * Math.pow(0.01, 1 - Bg);
                    QTT = QoG0;
                    QTT2 = Math.pow((QMA - 0.5 * QTT) / (AAG / ((1 - Bg) * Ut)), 1 / (1 - Bg));
                    while (Math.abs(QTT2 - QTT) > err_limit_q) {
                        QTT = QTT2;
                        QTT2 = Math.pow((QMA - 0.5 * QTT) / (AAG / ((1 - Bg) * Ut)), 1 / (1 - Bg));
                    }
                    QG[i] = QTT2;
                }
            } else { // 退水
                QG[i] = QoS0 * Math.pow(1 + Bs / AAS * Math.pow(QoS0, Bs), (-1) / Bs);
            }
            QW[i] = QS[i] + QG[i];
            QG0[i + 1] = QG[i];
            QW0[i + 1] = QW[i];
        }
    }

    private List<String> toStringList(double[] array0) {
        String[] array = new String[array0.length];
        for (int i = 0; i < array.length; i++) {
            array[i] = String.valueOf(array0[i]);
        }
        return Arrays.asList(array);
    }

    @Override
    public void init() {

    }

    @Override
    public PredictResult predict() {
        PredictResult result = new PredictResult();
        Map<String, double[]> map = HBmodel();

        double[][] RSim = new double[2][];
        //流域地表产流
        RSim[0] = map.get("RS");
        //流域地下产流
        RSim[1] = map.get("RG");

        //流域面积总产流，流域地表产流 RS[j] + 流域地下产流RG[j];
        result.setRunoffSim(map.get("R"));
        result.setRSim(RSim);

        //流域汇流
        result.setQSim(map.get("QSim"));

        //更新状态
        List<String> WP = toStringList(Pa);
        List<String> WI = toStringList(I);
        List<String> QS = toStringList(QS0);
        List<String> QG = toStringList(QG0);
        List<String> QW = toStringList(QW0);

        Map<String, List<String>> status = new HashMap<>();
        status.put("WP", WP);
        status.put("WI", WP);
        status.put("QS", QS);
        status.put("QG", QG);
        status.put("QW", QW);

        result.setNewStatus(status);

        return result;
    }

    public static void main(String[] args) {
        String a = "{\"WMX\":\"0.9\",\"BG\":\"0.5\",\"F\":\"475.977\",\"I0\":\"0\",\"FM\":\"50\",\"N\":\"0.5\",\"dt\":\"[\\\"2021-07-15 08:00:00\\\",\\\"2021-07-15 14:00:00\\\",\\\"2021-07-15 20:00:00\\\",\\\"2021-07-16 02:00:00\\\",\\\"2021-07-16 08:00:00\\\",\\\"2021-07-16 14:00:00\\\",\\\"2021-07-16 20:00:00\\\",\\\"2021-07-17 02:00:00\\\",\\\"2021-07-17 08:00:00\\\",\\\"2021-07-17 14:00:00\\\",\\\"2021-07-17 20:00:00\\\",\\\"2021-07-18 02:00:00\\\",\\\"2021-07-18 08:00:00\\\",\\\"2021-07-18 14:00:00\\\",\\\"2021-07-18 20:00:00\\\",\\\"2021-07-19 02:00:00\\\",\\\"2021-07-19 08:00:00\\\",\\\"2021-07-19 14:00:00\\\",\\\"2021-07-19 20:00:00\\\",\\\"2021-07-20 02:00:00\\\",\\\"2021-07-20 08:00:00\\\",\\\"2021-07-20 14:00:00\\\",\\\"2021-07-20 20:00:00\\\",\\\"2021-07-21 02:00:00\\\",\\\"2021-07-21 08:00:00\\\",\\\"2021-07-21 14:00:00\\\",\\\"2021-07-21 20:00:00\\\",\\\"2021-07-22 02:00:00\\\",\\\"2021-07-22 08:00:00\\\",\\\"2021-07-22 14:00:00\\\",\\\"2021-07-22 20:00:00\\\",\\\"2021-07-23 02:00:00\\\",\\\"2021-07-23 08:00:00\\\",\\\"2021-07-23 14:00:00\\\",\\\"2021-07-23 20:00:00\\\",\\\"2021-07-24 02:00:00\\\",\\\"2021-07-24 08:00:00\\\",\\\"2021-07-24 14:00:00\\\",\\\"2021-07-24 20:00:00\\\",\\\"2021-07-25 02:00:00\\\",\\\"2021-07-25 08:00:00\\\",\\\"2021-07-25 14:00:00\\\",\\\"2021-07-25 20:00:00\\\",\\\"2021-07-26 02:00:00\\\",\\\"2021-07-26 08:00:00\\\",\\\"2021-07-26 14:00:00\\\",\\\"2021-07-26 20:00:00\\\",\\\"2021-07-27 02:00:00\\\",\\\"2021-07-27 08:00:00\\\",\\\"2021-07-27 14:00:00\\\",\\\"2021-07-27 20:00:00\\\",\\\"2021-07-28 02:00:00\\\",\\\"2021-07-28 08:00:00\\\",\\\"2021-07-28 14:00:00\\\",\\\"2021-07-28 20:00:00\\\",\\\"2021-07-29 02:00:00\\\",\\\"2021-07-29 08:00:00\\\",\\\"2021-07-29 14:00:00\\\",\\\"2021-07-29 20:00:00\\\",\\\"2021-07-30 02:00:00\\\",\\\"2021-07-30 08:00:00\\\",\\\"2021-07-30 14:00:00\\\",\\\"2021-07-30 20:00:00\\\",\\\"2021-07-31 02:00:00\\\",\\\"2021-07-31 08:00:00\\\",\\\"2021-07-31 14:00:00\\\",\\\"2021-07-31 20:00:00\\\",\\\"2021-08-01 02:00:00\\\",\\\"2021-08-01 08:00:00\\\",\\\"2021-08-01 14:00:00\\\",\\\"2021-08-01 20:00:00\\\",\\\"2021-08-02 02:00:00\\\",\\\"2021-08-02 08:00:00\\\",\\\"2021-08-02 14:00:00\\\",\\\"2021-08-02 20:00:00\\\",\\\"2021-08-03 02:00:00\\\",\\\"2021-08-03 08:00:00\\\",\\\"2021-08-03 14:00:00\\\",\\\"2021-08-03 20:00:00\\\",\\\"2021-08-04 02:00:00\\\",\\\"2021-08-04 08:00:00\\\",\\\"2021-08-04 14:00:00\\\",\\\"2021-08-04 20:00:00\\\",\\\"2021-08-05 02:00:00\\\",\\\"2021-08-05 08:00:00\\\",\\\"2021-08-05 14:00:00\\\",\\\"2021-08-05 20:00:00\\\",\\\"2021-08-06 02:00:00\\\",\\\"2021-08-06 08:00:00\\\",\\\"2021-08-06 14:00:00\\\",\\\"2021-08-06 20:00:00\\\",\\\"2021-08-07 02:00:00\\\",\\\"2021-08-07 08:00:00\\\",\\\"2021-08-07 14:00:00\\\",\\\"2021-08-07 20:00:00\\\",\\\"2021-08-08 02:00:00\\\",\\\"2021-08-08 08:00:00\\\",\\\"2021-08-08 14:00:00\\\",\\\"2021-08-08 20:00:00\\\",\\\"2021-08-09 02:00:00\\\",\\\"2021-08-09 08:00:00\\\",\\\"2021-08-09 14:00:00\\\",\\\"2021-08-09 20:00:00\\\",\\\"2021-08-10 02:00:00\\\",\\\"2021-08-10 08:00:00\\\",\\\"2021-08-10 14:00:00\\\",\\\"2021-08-10 20:00:00\\\",\\\"2021-08-11 02:00:00\\\",\\\"2021-08-11 08:00:00\\\",\\\"2021-08-11 14:00:00\\\",\\\"2021-08-11 20:00:00\\\",\\\"2021-08-12 02:00:00\\\",\\\"2021-08-12 08:00:00\\\",\\\"2021-08-12 14:00:00\\\",\\\"2021-08-12 20:00:00\\\",\\\"2021-08-13 02:00:00\\\",\\\"2021-08-13 08:00:00\\\",\\\"2021-08-13 14:00:00\\\",\\\"2021-08-13 20:00:00\\\",\\\"2021-08-14 02:00:00\\\",\\\"2021-08-14 08:00:00\\\",\\\"2021-08-14 14:00:00\\\",\\\"2021-08-14 20:00:00\\\",\\\"2021-08-15 02:00:00\\\",\\\"2021-08-15 08:00:00\\\",\\\"2021-08-15 14:00:00\\\",\\\"2021-08-15 20:00:00\\\",\\\"2021-08-16 02:00:00\\\",\\\"2021-08-16 08:00:00\\\",\\\"2021-08-16 14:00:00\\\",\\\"2021-08-16 20:00:00\\\",\\\"2021-08-17 02:00:00\\\",\\\"2021-08-17 08:00:00\\\",\\\"2021-08-17 14:00:00\\\",\\\"2021-08-17 20:00:00\\\",\\\"2021-08-18 02:00:00\\\",\\\"2021-08-18 08:00:00\\\",\\\"2021-08-18 14:00:00\\\",\\\"2021-08-18 20:00:00\\\",\\\"2021-08-19 02:00:00\\\",\\\"2021-08-19 08:00:00\\\",\\\"2021-08-19 14:00:00\\\",\\\"2021-08-19 20:00:00\\\",\\\"2021-08-20 02:00:00\\\",\\\"2021-08-20 08:00:00\\\",\\\"2021-08-20 14:00:00\\\",\\\"2021-08-20 20:00:00\\\",\\\"2021-08-21 02:00:00\\\",\\\"2021-08-21 08:00:00\\\",\\\"2021-08-21 14:00:00\\\",\\\"2021-08-21 20:00:00\\\",\\\"2021-08-22 02:00:00\\\",\\\"2021-08-22 08:00:00\\\",\\\"2021-08-22 14:00:00\\\",\\\"2021-08-22 20:00:00\\\",\\\"2021-08-23 02:00:00\\\",\\\"2021-08-23 08:00:00\\\",\\\"2021-08-23 14:00:00\\\",\\\"2021-08-23 20:00:00\\\",\\\"2021-08-24 02:00:00\\\",\\\"2021-08-24 08:00:00\\\",\\\"2021-08-24 14:00:00\\\",\\\"2021-08-24 20:00:00\\\",\\\"2021-08-25 02:00:00\\\",\\\"2021-08-25 08:00:00\\\",\\\"2021-08-25 14:00:00\\\",\\\"2021-08-25 20:00:00\\\",\\\"2021-08-26 02:00:00\\\",\\\"2021-08-26 08:00:00\\\",\\\"2021-08-26 14:00:00\\\",\\\"2021-08-26 20:00:00\\\",\\\"2021-08-27 02:00:00\\\",\\\"2021-08-27 08:00:00\\\",\\\"2021-08-27 14:00:00\\\",\\\"2021-08-27 20:00:00\\\",\\\"2021-08-28 02:00:00\\\",\\\"2021-08-28 08:00:00\\\",\\\"2021-08-28 14:00:00\\\",\\\"2021-08-28 20:00:00\\\",\\\"2021-08-29 02:00:00\\\",\\\"2021-08-29 08:00:00\\\",\\\"2021-08-29 14:00:00\\\",\\\"2021-08-29 20:00:00\\\",\\\"2021-08-30 02:00:00\\\",\\\"2021-08-30 08:00:00\\\",\\\"2021-08-30 14:00:00\\\",\\\"2021-08-30 20:00:00\\\",\\\"2021-08-31 02:00:00\\\",\\\"2021-08-31 08:00:00\\\",\\\"2021-08-31 14:00:00\\\",\\\"2021-08-31 20:00:00\\\",\\\"2021-09-01 02:00:00\\\",\\\"2021-09-01 08:00:00\\\",\\\"2021-09-01 14:00:00\\\",\\\"2021-09-01 20:00:00\\\",\\\"2021-09-02 02:00:00\\\",\\\"2021-09-02 08:00:00\\\",\\\"2021-09-02 14:00:00\\\",\\\"2021-09-02 20:00:00\\\",\\\"2021-09-03 02:00:00\\\",\\\"2021-09-03 08:00:00\\\",\\\"2021-09-03 14:00:00\\\",\\\"2021-09-03 20:00:00\\\",\\\"2021-09-04 02:00:00\\\",\\\"2021-09-04 08:00:00\\\",\\\"2021-09-04 14:00:00\\\",\\\"2021-09-04 20:00:00\\\",\\\"2021-09-05 02:00:00\\\",\\\"2021-09-05 08:00:00\\\",\\\"2021-09-05 14:00:00\\\",\\\"2021-09-05 20:00:00\\\",\\\"2021-09-06 02:00:00\\\",\\\"2021-09-06 08:00:00\\\",\\\"2021-09-06 14:00:00\\\",\\\"2021-09-06 20:00:00\\\",\\\"2021-09-07 02:00:00\\\",\\\"2021-09-07 08:00:00\\\",\\\"2021-09-07 14:00:00\\\",\\\"2021-09-07 20:00:00\\\",\\\"2021-09-08 02:00:00\\\",\\\"2021-09-08 08:00:00\\\",\\\"2021-09-08 14:00:00\\\",\\\"2021-09-08 20:00:00\\\",\\\"2021-09-09 02:00:00\\\",\\\"2021-09-09 08:00:00\\\",\\\"2021-09-09 14:00:00\\\",\\\"2021-09-09 20:00:00\\\",\\\"2021-09-10 02:00:00\\\",\\\"2021-09-10 08:00:00\\\",\\\"2021-09-10 14:00:00\\\",\\\"2021-09-10 20:00:00\\\",\\\"2021-09-11 02:00:00\\\",\\\"2021-09-11 08:00:00\\\",\\\"2021-09-11 14:00:00\\\",\\\"2021-09-11 20:00:00\\\",\\\"2021-09-12 02:00:00\\\",\\\"2021-09-12 08:00:00\\\",\\\"2021-09-12 14:00:00\\\",\\\"2021-09-12 20:00:00\\\",\\\"2021-09-13 02:00:00\\\",\\\"2021-09-13 08:00:00\\\",\\\"2021-09-13 14:00:00\\\",\\\"2021-09-13 20:00:00\\\",\\\"2021-09-14 02:00:00\\\",\\\"2021-09-14 08:00:00\\\",\\\"2021-09-14 14:00:00\\\",\\\"2021-09-14 20:00:00\\\",\\\"2021-09-15 02:00:00\\\",\\\"2021-09-15 08:00:00\\\",\\\"2021-09-15 14:00:00\\\",\\\"2021-09-15 20:00:00\\\",\\\"2021-09-16 02:00:00\\\",\\\"2021-09-16 08:00:00\\\",\\\"2021-09-16 14:00:00\\\",\\\"2021-09-16 20:00:00\\\",\\\"2021-09-17 02:00:00\\\",\\\"2021-09-17 08:00:00\\\",\\\"2021-09-17 14:00:00\\\",\\\"2021-09-17 20:00:00\\\",\\\"2021-09-18 02:00:00\\\",\\\"2021-09-18 08:00:00\\\",\\\"2021-09-18 14:00:00\\\",\\\"2021-09-18 20:00:00\\\",\\\"2021-09-19 02:00:00\\\",\\\"2021-09-19 08:00:00\\\",\\\"2021-09-19 14:00:00\\\",\\\"2021-09-19 20:00:00\\\",\\\"2021-09-20 02:00:00\\\",\\\"2021-09-20 08:00:00\\\",\\\"2021-09-20 14:00:00\\\",\\\"2021-09-20 20:00:00\\\",\\\"2021-09-21 02:00:00\\\",\\\"2021-09-21 08:00:00\\\",\\\"2021-09-21 14:00:00\\\",\\\"2021-09-21 20:00:00\\\",\\\"2021-09-22 02:00:00\\\",\\\"2021-09-22 08:00:00\\\",\\\"2021-09-22 14:00:00\\\",\\\"2021-09-22 20:00:00\\\",\\\"2021-09-23 02:00:00\\\",\\\"2021-09-23 08:00:00\\\",\\\"2021-09-23 14:00:00\\\",\\\"2021-09-23 20:00:00\\\",\\\"2021-09-24 02:00:00\\\",\\\"2021-09-24 08:00:00\\\",\\\"2021-09-24 14:00:00\\\",\\\"2021-09-24 20:00:00\\\",\\\"2021-09-25 02:00:00\\\",\\\"2021-09-25 08:00:00\\\",\\\"2021-09-25 14:00:00\\\",\\\"2021-09-25 20:00:00\\\",\\\"2021-09-26 02:00:00\\\",\\\"2021-09-26 08:00:00\\\",\\\"2021-09-26 14:00:00\\\",\\\"2021-09-26 20:00:00\\\",\\\"2021-09-27 02:00:00\\\",\\\"2021-09-27 08:00:00\\\",\\\"2021-09-27 14:00:00\\\",\\\"2021-09-27 20:00:00\\\",\\\"2021-09-28 02:00:00\\\",\\\"2021-09-28 08:00:00\\\",\\\"2021-09-28 14:00:00\\\",\\\"2021-09-28 20:00:00\\\",\\\"2021-09-29 02:00:00\\\",\\\"2021-09-29 08:00:00\\\",\\\"2021-09-29 14:00:00\\\",\\\"2021-09-29 20:00:00\\\",\\\"2021-09-30 02:00:00\\\",\\\"2021-09-30 08:00:00\\\",\\\"2021-09-30 14:00:00\\\",\\\"2021-09-30 20:00:00\\\",\\\"2021-10-01 02:00:00\\\",\\\"2021-10-01 08:00:00\\\"]\",\"BS\":\"0.2\",\"U\":\"0.5\",\"WM\":\"100\",\"X\":\"0.01\",\"PA0\":\"0\",\"rain\":\"[1.319680962112E-17,0.2558612000000001,12.1001096,0.2558612000000001,0.2558612000000001,0.08777150000000002,0.0045651,0.2541843,0.0045651,0.0,0.0,0.0,0.0,0.3015507,0.3431539,0.3015507,0.3015507,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.15810625,1.15810625,1.15810625,1.15810625,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.08320640000000001,0.0,0.04160320000000001,3.0515106595295594,2.9267010595295595,3.36369935952956,33.050622954781,0.0,0.0,0.0,0.0,0.5983811,0.3903651,0.3487619,0.4319683,4.3616048532335,5.1711305263037,6.1568531695224,5.974994597267,4.67753269528,4.792357323045,3.3678980830015,3.3477355519147,0.42158457724506004,1.52744538518,0.42158457724506004,0.42158457724506004,0.55152185,0.46831544999999997,0.46831544999999997,0.46831544999999997,7.6085E-4,7.6085E-4,7.6085E-4,7.6085E-4,2.1617202928701857,2.1617202928701857,2.1617202928701857,4.0708943828964,0.29441715,0.25281395,0.29441715,0.41922675000000004,7.6085E-4,7.6085E-4,7.6085E-4,7.6085E-4,0.06695480000000001,0.06695480000000001,0.06695480000000001,0.06695480000000001,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.08320640000000001,1.1257894999999998,1.0425830999999999,1.4586150999999998,1.0425830999999999,0.77760924076122,7.928316140305,0.77760924076122,0.77760924076122,0.79049605,2.6210368500000003,0.74889285,0.74889285,2.6120155499999997,2.82003155,2.77842835,2.6120155499999997,0.40663655000000004,0.6146525500000001,0.40663655000000004,0.40663655000000004,1.9058621,1.8642589,1.9058621,5.2360579000000005,10.576118258238498,5.468518836507201,5.1944820070249245,4.944862807024925,3.5248685580159997,2.81962695,0.4462315500000001,0.4462315500000001,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,6.256730521714001,12.724962643375997,3.0805410014562,2.7893185806545997,0.0,0.0,0.0,0.0,7.6085E-4,7.6085E-4,7.6085E-4,0.37518965,0.04160320000000001,0.0,0.04160320000000001,0.0,3.4295581760332006,3.4295581760332006,4.5787310021126,8.562139402252,0.00238179131758,0.444312414178,0.00238179131758,0.25200099131757997,0.09157575000000001,0.008369350000000001,0.008369350000000001,0.008369350000000001,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.04160320000000001,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.16641280000000003,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.416398,0.416398,0.416398,0.416398,0.0,7.969591599999999,0.0,0.260728,0.0,0.0,0.0,0.0,0.00684765,0.00684765,0.25646684999999997,0.00684765,1.8252967,1.8668999,2.0749159,2.5325511624048,5.937636131672001,1.78723637678226,1.7456331767822604,1.78723637678226,7.6085E-4,7.6085E-4,7.6085E-4,7.6085E-4,1.6897376499999999,1.77294405,1.6897376499999999,4.7683744500000005,0.864961625,2.3210735417936,0.7817552249999999,0.8233584249999999,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.7771071840942,1.0140856848572601,4.34055114588706,1.0140856848572601,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.031955700000000004,0.031955700000000004,0.031955700000000004,0.4479877,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,3.4196515748284,3.4196515748284,3.4196515748284,6.139262408061,11.6535890218,8.033393197267,6.1101215891319995,5.6102431908698,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,5.0583741475286,5.0583741475286,5.17946942357,5.240017057025599,0.0015217,0.0015217,0.0015217,0.0015217,0.03575995,0.03575995,0.03575995,0.03575995,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0]\",\"AG\":\"3600\",\"start\":\"\\\"2021-08-14 08:00:00\\\"\",\"ES\":\"[5.4, 11.1, 38.1, 96.2, 124, 108.8, 93.9, 91.2, 62.5, 45.6, 17.2, 4.7]\",\"STARTQ\":\"1\",\"q\":\"[]\",\"AS\":\"3600\",\"EX\":\"0.5\",\"TG\":\"3\",\"runoffSim\":\"[]\",\"clen\":\"6\",\"FC\":\"2\",\"TS\":\"6\"}";
        Map data = JSON.parseObject(a, Map.class);
        HBMODEL obj = new HBMODEL(data);
        System.out.println(obj.predict());
    }
}
